/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package DTD.Validador;

import DTD.DTDTool;
import DTD.Diccionario.Diccionario;
import DTD.Diccionario.IDiccionario;
import Utilidades.StrOp;
import Utilidades.VerificadorStrings;

/**
 *
 * @author Administrador
 */
public class ValidadorSintaxisAtributo{

    private final int LIST      = 0;
    private final int DATA_TYPE = 1;
    private final int ERROR     = -1;
    private final int REQ       = 2;
    private int tipoAux1;
    private int tipoAux2;
    private int tipoAux3;
    private Diccionario diccionario;
    private String[] valoresPosibles;

    public ValidadorSintaxisAtributo() {
        diccionario = new Diccionario();
    }

    public boolean validar(String[] reglas) {
        boolean resultado = true;

        for (int i = 0; i < reglas.length; i++) {
            String regla = reglas[i];
            if (this.validarRegla(regla) == false) {
                resultado = false;
                break;
            }
        }
        return resultado;
    }

    private boolean validarValoresPosibles() {
        boolean resultado = true;

        for (int i = 0; i < valoresPosibles.length; i++) {
            String string = valoresPosibles[i];
            if (VerificadorStrings.soloTextosYGuiones(string) == false) {
                resultado = false;
            }
        }
        return resultado;
    }

    private boolean validarRegla(String regla) {
        boolean resultado = true;
        String[] lista = StrOp.separar(regla, " ", "", "", '(', ')');

        if (lista.length == 3 || lista.length == 4) {
            String aux0 = lista[0];
            String aux1 = lista[1];
            String aux2 = lista[2];
            String aux3 = null;

            if (lista.length == 4) {
                aux3 = lista[3];
            }
            if (validarAux0(aux0) == false) {
                resultado = false;
            }
            else if (validarAux1Aux2(aux1, aux2) == false) {
                resultado = false;
            }
            else if (aux3 != null && validarAux3(aux3) == false) {
                resultado = false;
            }
        }
        else {
            resultado = false;
        }
        return resultado;
    }

    private boolean validarSeparador(final String str, int i) {
        String s = StrOp.borrarInicioFin(str, "(", ")");
        return DTDTool.getCantidadSalidasPar(s, '|') == i;
    }

    private boolean validarAux0(String aux0) {
        boolean resultado = true;

        if (VerificadorStrings.soloTextosYGuiones(aux0) == false) {
            resultado = false;
        }
        else if (this.diccionario.existe(aux0) == true) {
            resultado = false;
        }
        return resultado;
    }

    private boolean validarAux1Aux2(String aux1, String aux2) {
        boolean resultado = true;

        if (validarAux1(aux1) == false) {
            resultado = false;
        }
        else if (validarAux2(aux2) == false) {
            resultado = false;
        }
        return resultado;
    }

    private boolean validarAux1(String aux1) {
        boolean resultado = true;
        this.tipoAux1 = getTipo(aux1);

        if (this.tipoAux1 == this.ERROR) {
            resultado = false;
        }
        else if (this.tipoAux1 == this.REQ) {
            resultado = false;
        }

        if (this.tipoAux1 == this.LIST) {
            //solo se cargan los posibles valores si es del tipo lista
            this.valoresPosibles = StrOp.separar(aux1, "[|]", "(", ")", '"', '"');
            if (validarSeparador(aux1, this.valoresPosibles.length - 1) == false) {
                resultado = false;
            }
            else if (StrOp.getCantidadDe(aux1, '|') != this.valoresPosibles.length - 1) {
                resultado = false;
            }
            else if (this.valoresPosibles != null && validarValoresPosibles() == false) {
                resultado = false;
            }
        }
        return resultado;
    }

    private boolean validarAux2(String aux2) {
        boolean resultado = true;
        this.tipoAux2 = this.getTipo(aux2);

        if (this.tipoAux2 == this.ERROR) {
            resultado = false;
        }
        else if (this.tipoAux1 == this.DATA_TYPE && this.tipoAux2 != this.REQ) {
            resultado = false;
        }
        else if (this.tipoAux1 == this.LIST && validarDefault(aux2) == false) {
            resultado = false;
        }
        return resultado;
    }

    private boolean validarAux3(String aux3) {
        boolean resultado = true;
        this.tipoAux3 = this.getTipo(aux3);

        if (aux3 != null) {
            if (this.tipoAux3 == this.ERROR) {
                resultado = false;
            }
            else if (this.tipoAux3 != this.REQ) {
                resultado = false;
            }
            else if (this.tipoAux2 == this.REQ) {
                resultado = false;
            }
        }
        return resultado;
    }

    private boolean validarDefault(String aux2) {
        boolean resultado = true;

        if (this.tipoAux2 != this.REQ) {
            resultado = false;
            for (int i = 0; i < valoresPosibles.length; i++) {
                String aux = valoresPosibles[i];
                if (aux.equals(aux2) == true) {
                    resultado = true;
                    break;
                }
            }
        }
        return resultado;
    }

    private int getTipo(String aux123) {
        int resultado = this.ERROR;
        boolean aux = true;
        aux = (resultado == this.ERROR);
        aux = aux && VerificadorStrings.tieneIgualDe(aux123, "()", 1, true);
        aux = aux && (this.diccionario.existe(aux123) == false);

        if (aux == true) {
            resultado = this.LIST;
        }

        aux = (resultado == this.ERROR);
        aux = aux && diccionario.getTipoDiccionario(aux123) == IDiccionario.ATT_OPCIONAL;

        if (aux == true) {
            resultado = this.REQ;
        }

        aux = (resultado == this.ERROR);
        aux = aux && diccionario.getTipoDiccionario(aux123) == IDiccionario.DATA_TYPE;

        if (aux == true) {
            resultado = this.DATA_TYPE;
        }
        return resultado;
    }
}
